package reamodel.diagram.providers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.ModelingAssistantProvider;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;

import reamodel.diagram.edit.parts.DecrementCommitmentEditPart;
import reamodel.diagram.edit.parts.DecrementEconomicEventEditPart;
import reamodel.diagram.edit.parts.DecrementEconomicEventTypeEditPart;
import reamodel.diagram.edit.parts.EconomicAgentEditPart;
import reamodel.diagram.edit.parts.EconomicAgentTypeEditPart;
import reamodel.diagram.edit.parts.EconomicResourceEditPart;
import reamodel.diagram.edit.parts.EconomicResourceTypeEditPart;
import reamodel.diagram.edit.parts.IncrementCommitmentEditPart;
import reamodel.diagram.edit.parts.IncrementEconomicEventEditPart;
import reamodel.diagram.edit.parts.IncrementEconomicEventTypeEditPart;
import reamodel.diagram.edit.parts.REAModelEditPart;
import reamodel.diagram.part.Messages;
import reamodel.diagram.part.REAmetamodelDiagramEditorPlugin;

/**
 * @generated
 */
public class REAmetamodelModelingAssistantProvider extends
		ModelingAssistantProvider {

	/**
	 * @generated
	 */
	public List getTypesForPopupBar(IAdaptable host) {
		IGraphicalEditPart editPart = (IGraphicalEditPart) host
				.getAdapter(IGraphicalEditPart.class);
		if (editPart instanceof REAModelEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.EconomicResourceType_1001);
			types.add(REAmetamodelElementTypes.EconomicAgentType_1002);
			types.add(REAmetamodelElementTypes.DecrementEconomicEventType_1003);
			types.add(REAmetamodelElementTypes.IncrementEconomicEventType_1004);
			types.add(REAmetamodelElementTypes.EconomicAgent_1005);
			types.add(REAmetamodelElementTypes.EconomicResource_1006);
			types.add(REAmetamodelElementTypes.DecrementEconomicEvent_1007);
			types.add(REAmetamodelElementTypes.IncrementEconomicEvent_1008);
			types.add(REAmetamodelElementTypes.IncrementCommitment_1009);
			types.add(REAmetamodelElementTypes.DecrementCommitment_1010);
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnSource(IAdaptable source) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof EconomicResourceTypeEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.EconomicResourceTypeTypify_3001);
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentTypeEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.EconomicAgentTypeTypify_3008);
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.DecrementEconomicEventTypeTypify_3004);
			types.add(REAmetamodelElementTypes.OutflowType_3006);
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventTypeTypify_3005);
			types.add(REAmetamodelElementTypes.InflowType_3007);
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventTypeDualityType_3012);
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.ReceiveParticipation_3009);
			types.add(REAmetamodelElementTypes.ProvideParticipation_3010);
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.Outflow_3002);
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.Inflow_3003);
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventDuality_3011);
			return types;
		}
		if (sourceEditPart instanceof IncrementCommitmentEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.IncrementCommitmentFulfill_3015);
			types
					.add(REAmetamodelElementTypes.IncrementCommitmentReciprocity_3017);
			types.add(REAmetamodelElementTypes.IncrementCommitmentSpecify_3019);
			return types;
		}
		if (sourceEditPart instanceof DecrementCommitmentEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.DecrementCommitmentFulfill_3016);
			types.add(REAmetamodelElementTypes.DecrementCommitmentSpecify_3018);
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnTarget(IAdaptable target) {
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (targetEditPart instanceof EconomicResourceTypeEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.OutflowType_3006);
			types.add(REAmetamodelElementTypes.InflowType_3007);
			types.add(REAmetamodelElementTypes.CommitmentResource_3014);
			return types;
		}
		if (targetEditPart instanceof EconomicAgentTypeEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.CommitmentAgent_3013);
			return types;
		}
		if (targetEditPart instanceof DecrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventTypeDualityType_3012);
			types.add(REAmetamodelElementTypes.DecrementCommitmentSpecify_3018);
			return types;
		}
		if (targetEditPart instanceof IncrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.IncrementCommitmentSpecify_3019);
			return types;
		}
		if (targetEditPart instanceof EconomicAgentEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.EconomicAgentTypeTypify_3008);
			return types;
		}
		if (targetEditPart instanceof EconomicResourceEditPart) {
			List types = new ArrayList();
			types.add(REAmetamodelElementTypes.EconomicResourceTypeTypify_3001);
			types.add(REAmetamodelElementTypes.Outflow_3002);
			types.add(REAmetamodelElementTypes.Inflow_3003);
			return types;
		}
		if (targetEditPart instanceof DecrementEconomicEventEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.DecrementEconomicEventTypeTypify_3004);
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventDuality_3011);
			types.add(REAmetamodelElementTypes.DecrementCommitmentFulfill_3016);
			return types;
		}
		if (targetEditPart instanceof IncrementEconomicEventEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.IncrementEconomicEventTypeTypify_3005);
			types.add(REAmetamodelElementTypes.IncrementCommitmentFulfill_3015);
			return types;
		}
		if (targetEditPart instanceof DecrementCommitmentEditPart) {
			List types = new ArrayList();
			types
					.add(REAmetamodelElementTypes.IncrementCommitmentReciprocity_3017);
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnSourceAndTarget(IAdaptable source,
			IAdaptable target) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof EconomicResourceTypeEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof EconomicResourceEditPart) {
				types
						.add(REAmetamodelElementTypes.EconomicResourceTypeTypify_3001);
			}
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentTypeEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof EconomicAgentEditPart) {
				types
						.add(REAmetamodelElementTypes.EconomicAgentTypeTypify_3008);
			}
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof DecrementEconomicEventEditPart) {
				types
						.add(REAmetamodelElementTypes.DecrementEconomicEventTypeTypify_3004);
			}
			if (targetEditPart instanceof EconomicResourceTypeEditPart) {
				types.add(REAmetamodelElementTypes.OutflowType_3006);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof IncrementEconomicEventEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventTypeTypify_3005);
			}
			if (targetEditPart instanceof EconomicResourceTypeEditPart) {
				types.add(REAmetamodelElementTypes.InflowType_3007);
			}
			if (targetEditPart instanceof DecrementEconomicEventTypeEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventTypeDualityType_3012);
			}
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentEditPart) {
			List types = new ArrayList();
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof EconomicResourceEditPart) {
				types.add(REAmetamodelElementTypes.Outflow_3002);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof EconomicResourceEditPart) {
				types.add(REAmetamodelElementTypes.Inflow_3003);
			}
			if (targetEditPart instanceof DecrementEconomicEventEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventDuality_3011);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementCommitmentEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof IncrementEconomicEventEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementCommitmentFulfill_3015);
			}
			if (targetEditPart instanceof DecrementCommitmentEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementCommitmentReciprocity_3017);
			}
			if (targetEditPart instanceof IncrementEconomicEventTypeEditPart) {
				types
						.add(REAmetamodelElementTypes.IncrementCommitmentSpecify_3019);
			}
			return types;
		}
		if (sourceEditPart instanceof DecrementCommitmentEditPart) {
			List types = new ArrayList();
			if (targetEditPart instanceof DecrementEconomicEventEditPart) {
				types
						.add(REAmetamodelElementTypes.DecrementCommitmentFulfill_3016);
			}
			if (targetEditPart instanceof DecrementEconomicEventTypeEditPart) {
				types
						.add(REAmetamodelElementTypes.DecrementCommitmentSpecify_3018);
			}
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getTypesForSource(IAdaptable target,
			IElementType relationshipType) {
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (targetEditPart instanceof EconomicResourceTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.OutflowType_3006) {
				types
						.add(REAmetamodelElementTypes.DecrementEconomicEventType_1003);
			}
			if (relationshipType == REAmetamodelElementTypes.InflowType_3007) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventType_1004);
			}
			return types;
		}
		if (targetEditPart instanceof EconomicAgentTypeEditPart) {
			List types = new ArrayList();
			return types;
		}
		if (targetEditPart instanceof DecrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventTypeDualityType_3012) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventType_1004);
			}
			if (relationshipType == REAmetamodelElementTypes.DecrementCommitmentSpecify_3018) {
				types.add(REAmetamodelElementTypes.DecrementCommitment_1010);
			}
			return types;
		}
		if (targetEditPart instanceof IncrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentSpecify_3019) {
				types.add(REAmetamodelElementTypes.IncrementCommitment_1009);
			}
			return types;
		}
		if (targetEditPart instanceof EconomicAgentEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.EconomicAgentTypeTypify_3008) {
				types.add(REAmetamodelElementTypes.EconomicAgentType_1002);
			}
			return types;
		}
		if (targetEditPart instanceof EconomicResourceEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.EconomicResourceTypeTypify_3001) {
				types.add(REAmetamodelElementTypes.EconomicResourceType_1001);
			}
			if (relationshipType == REAmetamodelElementTypes.Outflow_3002) {
				types.add(REAmetamodelElementTypes.DecrementEconomicEvent_1007);
			}
			if (relationshipType == REAmetamodelElementTypes.Inflow_3003) {
				types.add(REAmetamodelElementTypes.IncrementEconomicEvent_1008);
			}
			return types;
		}
		if (targetEditPart instanceof DecrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.DecrementEconomicEventTypeTypify_3004) {
				types
						.add(REAmetamodelElementTypes.DecrementEconomicEventType_1003);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventDuality_3011) {
				types.add(REAmetamodelElementTypes.IncrementEconomicEvent_1008);
			}
			if (relationshipType == REAmetamodelElementTypes.DecrementCommitmentFulfill_3016) {
				types.add(REAmetamodelElementTypes.DecrementCommitment_1010);
			}
			return types;
		}
		if (targetEditPart instanceof IncrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventTypeTypify_3005) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventType_1004);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentFulfill_3015) {
				types.add(REAmetamodelElementTypes.IncrementCommitment_1009);
			}
			return types;
		}
		if (targetEditPart instanceof DecrementCommitmentEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentReciprocity_3017) {
				types.add(REAmetamodelElementTypes.IncrementCommitment_1009);
			}
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getTypesForTarget(IAdaptable source,
			IElementType relationshipType) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof EconomicResourceTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.EconomicResourceTypeTypify_3001) {
				types.add(REAmetamodelElementTypes.EconomicResource_1006);
			}
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.EconomicAgentTypeTypify_3008) {
				types.add(REAmetamodelElementTypes.EconomicAgent_1005);
			}
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.DecrementEconomicEventTypeTypify_3004) {
				types.add(REAmetamodelElementTypes.DecrementEconomicEvent_1007);
			}
			if (relationshipType == REAmetamodelElementTypes.OutflowType_3006) {
				types.add(REAmetamodelElementTypes.EconomicResourceType_1001);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventTypeEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventTypeTypify_3005) {
				types.add(REAmetamodelElementTypes.IncrementEconomicEvent_1008);
			}
			if (relationshipType == REAmetamodelElementTypes.InflowType_3007) {
				types.add(REAmetamodelElementTypes.EconomicResourceType_1001);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventTypeDualityType_3012) {
				types
						.add(REAmetamodelElementTypes.DecrementEconomicEventType_1003);
			}
			return types;
		}
		if (sourceEditPart instanceof EconomicAgentEditPart) {
			List types = new ArrayList();
			return types;
		}
		if (sourceEditPart instanceof DecrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.Outflow_3002) {
				types.add(REAmetamodelElementTypes.EconomicResource_1006);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementEconomicEventEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.Inflow_3003) {
				types.add(REAmetamodelElementTypes.EconomicResource_1006);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementEconomicEventDuality_3011) {
				types.add(REAmetamodelElementTypes.DecrementEconomicEvent_1007);
			}
			return types;
		}
		if (sourceEditPart instanceof IncrementCommitmentEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentFulfill_3015) {
				types.add(REAmetamodelElementTypes.IncrementEconomicEvent_1008);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentReciprocity_3017) {
				types.add(REAmetamodelElementTypes.DecrementCommitment_1010);
			}
			if (relationshipType == REAmetamodelElementTypes.IncrementCommitmentSpecify_3019) {
				types
						.add(REAmetamodelElementTypes.IncrementEconomicEventType_1004);
			}
			return types;
		}
		if (sourceEditPart instanceof DecrementCommitmentEditPart) {
			List types = new ArrayList();
			if (relationshipType == REAmetamodelElementTypes.DecrementCommitmentFulfill_3016) {
				types.add(REAmetamodelElementTypes.DecrementEconomicEvent_1007);
			}
			if (relationshipType == REAmetamodelElementTypes.DecrementCommitmentSpecify_3018) {
				types
						.add(REAmetamodelElementTypes.DecrementEconomicEventType_1003);
			}
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public EObject selectExistingElementForSource(IAdaptable target,
			IElementType relationshipType) {
		return selectExistingElement(target, getTypesForSource(target,
				relationshipType));
	}

	/**
	 * @generated
	 */
	public EObject selectExistingElementForTarget(IAdaptable source,
			IElementType relationshipType) {
		return selectExistingElement(source, getTypesForTarget(source,
				relationshipType));
	}

	/**
	 * @generated
	 */
	protected EObject selectExistingElement(IAdaptable host, Collection types) {
		if (types.isEmpty()) {
			return null;
		}
		IGraphicalEditPart editPart = (IGraphicalEditPart) host
				.getAdapter(IGraphicalEditPart.class);
		if (editPart == null) {
			return null;
		}
		Diagram diagram = (Diagram) editPart.getRoot().getContents().getModel();
		Collection elements = new HashSet();
		for (Iterator it = diagram.getElement().eAllContents(); it.hasNext();) {
			EObject element = (EObject) it.next();
			if (isApplicableElement(element, types)) {
				elements.add(element);
			}
		}
		if (elements.isEmpty()) {
			return null;
		}
		return selectElement((EObject[]) elements.toArray(new EObject[elements
				.size()]));
	}

	/**
	 * @generated
	 */
	protected boolean isApplicableElement(EObject element, Collection types) {
		IElementType type = ElementTypeRegistry.getInstance().getElementType(
				element);
		return types.contains(type);
	}

	/**
	 * @generated
	 */
	protected EObject selectElement(EObject[] elements) {
		Shell shell = Display.getCurrent().getActiveShell();
		ILabelProvider labelProvider = new AdapterFactoryLabelProvider(
				REAmetamodelDiagramEditorPlugin.getInstance()
						.getItemProvidersAdapterFactory());
		ElementListSelectionDialog dialog = new ElementListSelectionDialog(
				shell, labelProvider);
		dialog
				.setMessage(Messages.REAmetamodelModelingAssistantProviderMessage);
		dialog.setTitle(Messages.REAmetamodelModelingAssistantProviderTitle);
		dialog.setMultipleSelection(false);
		dialog.setElements(elements);
		EObject selected = null;
		if (dialog.open() == Window.OK) {
			selected = (EObject) dialog.getFirstResult();
		}
		return selected;
	}
}
